package com.windea.study.kotlin.game.tankwar2

import com.windea.study.kotlin.game.tankwar2.core.*
import com.windea.study.kotlin.game.tankwar2.enums.*
import com.windea.study.kotlin.game.tankwar2.interfaces.*
import com.windea.study.kotlin.game.tankwar2.model.*
import javafx.scene.input.*
import java.io.*
import java.util.concurrent.*

/**项目的窗体。*/
class GameWindow : Window(
	GameConfig.title,
	GameConfig.icon,
	GameConfig.width,
	GameConfig.height
) {
	//线程安全的集合
	private val entities = CopyOnWriteArrayList<Entity>()
	// 晚点创建
	private lateinit var playerTank: PlayerTank
	//游戏是结束
	private var gameOver: Boolean = false
	//敌方的数量
	private var enemyTotalSize = 20
	//敌方坦克在界面上最多显示几个
	private var enemyActiveSize = 3
	//敌方的出生点
	private val enemyBornLocation = arrayListOf<Pair<Int, Int>>()
	//出生地点下标
	private var bornIndex = 0
	
	override fun onCreate() {
		//通过读文件的方式创建地图
		//NOTE toExternalForm()方法返回的是包含协议的路径
		val mapFile = File(javaClass.getResource("/map/1.map").toURI())
		var lineNum = 0
		mapFile.forEachLine { line ->
			var columnNum = 0
			// it  [空砖空砖空砖空砖空砖空砖空]
			line.toCharArray().forEach { column ->
				when(column) {
					'砖' -> entities += BrickWall(columnNum * GameConfig.block, lineNum * GameConfig.block)
					'铁' -> entities += SteelWall(columnNum * GameConfig.block, lineNum * GameConfig.block)
					'草' -> entities += Grass(columnNum * GameConfig.block, lineNum * GameConfig.block)
					'水' -> entities += Water(columnNum * GameConfig.block, lineNum * GameConfig.block)
					'敌' -> enemyBornLocation += Pair(columnNum * GameConfig.block, lineNum * GameConfig.block)
				}
				columnNum++
			}
			lineNum++
		}
		
		//添加我方的坦克
		playerTank = PlayerTank(GameConfig.block * 10, GameConfig.block * 12)
		entities += playerTank
		//添加大本营
		entities += Camp(GameConfig.width / 2 - GameConfig.block, GameConfig.height - 96)
	}
	
	override fun onDisplay() {
		//绘制图像
		
		//绘制地图中的元素
		entities.forEach {
			it.draw()
		}
	}
	
	//TODO 整合到其他事件中
	override fun onKeyPressed(event: KeyEvent) {
		if(gameOver) return
		
		//用户操作时
		when(event.code) {
			KeyCode.W -> playerTank.move(Direction.Up, entities)
			KeyCode.S -> playerTank.move(Direction.Down, entities)
			KeyCode.A -> playerTank.move(Direction.Left, entities)
			KeyCode.D -> playerTank.move(Direction.Right, entities)
			KeyCode.ENTER -> playerTank.attack(entities)
			else -> return
		}
	}
	
	//业务逻辑，比较耗时的操作
	override fun onRefresh() {
		//检测销毁，需要最先检测
		entities.filterIsInstance<Destroyable>().filter { it.isDestroyed() }.forEach { destroyable ->
			//判断具备销毁能力的物体，是否被销毁了
			entities.remove(destroyable)
			if(destroyable is EnemyTank) enemyTotalSize--
			destroyable.onDestroy(entities)
		}
		
		// 检测游戏是否结束
		if(entities.filterIsInstance<Camp>().isEmpty() || enemyTotalSize <= 0) gameOver = true
		if(gameOver) return
		
		// 判断运动的物体和阻塞物体是否发生碰撞
		//1） 找到运动的物体
		entities.filterIsInstance<Movable>().forEach { movable ->
			//2) 找到阻塞的物体
			var badDirection: Direction? = null
			var badBlockable: Blockable? = null
			
			//不要和自己比较
			entities.filterIsInstance<Blockable>().filter { movable != it }.forEach tag@{ blockable ->
				// 3) 遍历集合，找到是否发生碰撞
				//movable 和 block是否碰撞
				// 获得碰撞的方向
				val direction = movable.willCollision(blockable)
				
				//仅当未碰撞时才适用移动事件
				if(direction == null) {
					movable.onMove(entities)
					return@tag
				}
				
				//移动的发现碰撞。跳出当前循环
				badDirection = direction
				badBlockable = blockable
				return@tag
			}
			//找到和move碰撞的block，找到会碰撞的方向
			//通知可以移动的物体，会在哪个方向和哪个物体碰撞
			movable.onCollision(badBlockable, badDirection, entities)
		}
		
		// 检测自动移动能力的物体，让他们自己动起来
		entities.filterIsInstance<AutoMovable>().forEach {
			it.onAutoMove(entities)
		}
		
		//检测 具备攻击能力的和被攻击能力的物体间是否产生碰撞
		//1)过滤 具备攻击能力的
		entities.filterIsInstance<Attackable>().forEach { attackable ->
			//DONE 更加完善的有效攻击判定
			//子弹不会攻击到发射着
			//敌方坦克不会攻击到敌方坦克
			entities.filterIsInstance<Sufferable>().filter { sufferable ->
				attackable.owner != sufferable && !(attackable.owner is EnemyTank && sufferable is EnemyTank)
			}.forEach tag@{ sufferable ->
				//3) 判断是否产生碰撞
				if(attackable.isCollision(sufferable)) {
					//产生碰撞,找到碰撞者
					// 通知攻击者 产生碰撞
					attackable.onAttack(entities)
					// 通知被攻击者，产生碰撞
					sufferable.onSuffer(attackable, entities)
					
					return@tag
				}
			}
		}
		
		//检测自动射击
		entities.filterIsInstance<AutoAttackable>().forEach {
			it.onAutoAttack(entities)
		}
		
		// 检测敌方出生
		// 判断当前页面上敌方的数量，小于激活数量
		if(enemyTotalSize > 0 && entities.filterIsInstance<EnemyTank>().size < enemyActiveSize) {
			val index = bornIndex % enemyBornLocation.size
			val pair = enemyBornLocation[index]
			entities.add(EnemyTank(pair.first, pair.second))
			bornIndex++
		}
	}
}


